package cscalendar.classes;

import cscalendar.exceptions.CSCommandNotFoundException;
import cscalendar.exceptions.CSWrongCommandFormatException;
import cscalendar.interfaces.CSStorable;
import cscalendar.utility.Pair;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;

/**
 *
 * @author Muhammad Anis
 */
public class CSCommandManager implements CSStorable{

    public static final int MAX_COMMAND_IN_BUFFER = 10;
    
    HashMap<Integer, CSCommand> commandCollection;
    List<Pair<String,String>> commandLog;
    int activeCalendarId;

    /**
     * Constructor
     */
    public CSCommandManager() {
        this.commandCollection = new HashMap<>();
        this.commandLog = new ArrayList<>();
        activeCalendarId = 0;        
    }

    /**
     * Add a new calendar to calendar's collection
     * @param cal 
     */
    public void AddCalendarToCollection(CSCalendar cal) {
        this.commandCollection.put(cal.getEntryNo(), new CSCommand(cal));
        this.activeCalendarId = cal.getEntryNo();
    }

    /**
     * Execute a command given name and arguments
     * @param commandName name of command
     * @param args arguments
     * @throws NullPointerException if no calendar with associated active_id found
     */
    public void Execute(String commandName, String[] args) throws NullPointerException, CSWrongCommandFormatException {
        if (commandName.equalsIgnoreCase("Create")) {
            CSCalendar c = new CSCalendar(Integer.parseInt(args[1]));
            this.AddCalendarToCollection(c);
            AddCommandLog(commandName);
        } else if(commandName.equalsIgnoreCase("ShowCalendars")){
            printAllCalendar();           
        } else if (commandName.equalsIgnoreCase("SetCalendar")){
            if(args.length > 1){
                try{
                    int _id = Integer.parseInt(args[1]);
                    CSCommand c = commandCollection.get(_id);
                    if(c != null){
                        activeCalendarId = _id;
                    }
                }catch(NumberFormatException ex) {
                    throw new CSWrongCommandFormatException("Wrong Calendar ID format");
                }
            }else{
                throw new CSWrongCommandFormatException("Argument length must be 2");
            }
        }else {
            CSCommand command = commandCollection.get(this.activeCalendarId);
            if (command != null) {
                try {
                    command.Execute(commandName, args);
                    AddCommandLog(commandName);                    
                } catch (CSCommandNotFoundException ex) {
                    System.out.println(ex.getMessage());
                    printHelp();                    
                }
            } else {
                throw new NullPointerException("No Calendar with id : " + activeCalendarId + " , Have you create any Calendar?");
            }
        }
    }
    
    /**
     * Add command log
     * @param commandName 
     */
    private void AddCommandLog(String commandName){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        
        Pair pair = new Pair<>(commandName,sdf.format(Calendar.getInstance().getTime()));
        commandLog.add(pair);
        if(commandLog.size() > MAX_COMMAND_IN_BUFFER){
            this.saveToFile("command.log");
        }
    }

    /**
     * For main program
     */
    public void Execute() {
        Scanner in = new Scanner(System.in);
        String[] args;
        System.out.print("CSCalendar>");
        String s = in.nextLine();
        args = s.split("\\s+");
        while (!args[0].equalsIgnoreCase("Quit")) {
            try {
                this.Execute(args[0], args);
            } catch (NullPointerException | CSWrongCommandFormatException ex) {
                System.out.println(ex.getMessage());
            }
            System.out.print("CSCalendar>");
            s = in.nextLine();
            args = s.split("\\s+");
        }
        System.out.println("Bye bye :p");
    }

    /**
     * Save command in buffer, if size of command log in buffer more than MAX_COMMAND_IN_BUFFER
     * @param filePath 
     */
    @Override
    public void saveToFile(String filePath) {
        FileWriter fstream = null;
        try {
            fstream = new FileWriter(filePath, true);
            BufferedWriter buff_out = new BufferedWriter(fstream);
            for(Pair<String,String> pair : commandLog){
                buff_out.write(pair.getFirst()+"\t"+pair.getSecond());
                buff_out.newLine();
            }
            buff_out.close();
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        } finally {
            try {                
                fstream.close();                
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            }
        }
    }

    @Override
    public void loadFromFile(String filePath) {
        
    }

    private void printHelp() {
        System.out.println("Available Command :");
        System.out.println("Create");
        System.out.println("ShowCalendars");
        System.out.println("SetCalendar <calendar_id>");
        System.out.println("Add #eventid");
        System.out.println("View #eventid");
        System.out.println("Load #eventid");
        System.out.println("Save #eventid");
        System.out.println("Delete #eventid");
        System.out.println("ShowDetail #eventid");
        System.out.println("Info #eventid");
    }

    private void printAllCalendar() {
        for(Integer i : commandCollection.keySet()){            
            System.out.println("Calendar id : "+i);
        }
    }
}
